package com.asen.libcommon.util

import android.app.Activity
import android.content.*
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Rect
import android.graphics.drawable.GradientDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.os.Environment.MEDIA_MOUNTED
import android.provider.ContactsContract
import android.provider.ContactsContract.CommonDataKinds.*
import android.provider.ContactsContract.RawContacts
import android.provider.MediaStore
import android.text.TextUtils
import android.util.Base64
import android.util.TypedValue
import android.view.Gravity
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.ColorInt
import com.asen.libcommon.R
import com.asen.libcommon.util.permission.PermissionHelper
import com.asen.libcommon.widget.ToastUtils
import com.bumptech.glide.Glide
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.entity.LocalMedia
import java.io.*
import java.lang.reflect.Field
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import java.util.regex.Pattern


/**
 * @author 小强
 *
 * @time 2020/5/7  13:15
 *
 * @desc 常见工具类
 *
 */
object CommonUtil {


    /**
     * 检查手机号
     * @param context Context 上下文
     * @param phone String? 手机号
     * @param phoneRegex String? 手机号正则表达式
     * @return true：正确的 false：错误的
     */
    fun checkMobilePhone(context: Context, phone: String?, phoneRegex: String?): Boolean {
        if (phone.isNullOrEmpty()) {
            ToastUtils.showToast(context.getString(R.string.common_please_enter_your_mobile_number))
            return false
        }

        if (!isInternationalPhone(phone, phoneRegex)) {
            ToastUtils.showToast(context.getString(R.string.common_incorrect_format_of_mobile_number))
            return false
        }
        return true
    }


    /**
     * 验证国际区号 (中国国内+86 澳洲+61、 澳门 +853，香港+852)
     *
     * @param phone    手机号
     * @param phoneRegex    正则表达式
     * @return true：正确的 false：错误的
     */
    private fun isInternationalPhone(phone: String?, phoneRegex: String?): Boolean {

        if (phone.isNullOrEmpty()) {
            return false
        }

        if (phoneRegex.isNullOrEmpty()) {
            val regex =
                "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$"
            return if (phone?.length != 11) {
                false
            } else {
                val p = Pattern.compile(regex)
                val m = p.matcher(phone)
                m.matches()
            }
        }

        val p = Pattern.compile(phoneRegex)
        val m = p.matcher(phone)
        return m.matches()

    }

    /**
     * 验证密码 (密码需要8-20位，至少包含字母、数字、字符的任意两种)
     *
     * @param password    密码
     * @return true：正确的 false：错误的
     */
    fun isNewPassword(password: String?): Boolean {

        if (password.isNullOrEmpty()) {
            return false
        }

        val p = Pattern.compile("(?!^(\\d+|[a-zA-Z]+|[~!@#\$%^&*?]+)\$)^[\\w~!@#\$%^&*?]{8,20}$")
        val m = p.matcher(password)
        return m.matches()

    }

    /**
     * 只能输入中文正则表达式
     *
     * @param text    密码
     * @return true：是中文 false：不是中文
     */
    fun isChinese(text: String?): Boolean {

        if (text.isNullOrEmpty()) {
            return false
        }

        val p = Pattern.compile("^[\\u4e00-\\u9fa5]{0,}\$")
        val m = p.matcher(text)
        return m.matches()

    }


    /**
     * dp转px
     */
    fun dp2px(context: Context?, dpValue: Float): Int {
        return TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            dpValue,
            context?.resources?.displayMetrics
        ).toInt()
    }


    /**
     * px转dp
     */
    fun px2dp(context: Context?, pxValue: Float): Int {
        return (pxValue / (context?.resources?.displayMetrics?.density ?: 0f) + 0.5f).toInt()
    }


    /**
     * 将px值转换为sp值，保证文字大小不变
     * @param context
     * @param pxValue
     * @return
     */
    fun px2sp(context: Context?, pxValue: Float?): Float {
        return ((pxValue?.div(context?.resources?.displayMetrics?.scaledDensity ?: 0f))?.plus(0.5f))
            ?: 0f
    }

    /**
     * 名片单位转换
     * @param context 上下文
     * @param pxValue 转换的数据
     * @return 换算结果
     */
    fun getPx(context: Context?, pxValue: Float?): Int {
        return (getScreenWidth(context) / 750f * (pxValue ?: 0f) + 0.5).toInt()
    }

    /**
     * 将sp值转换为px值，保证文字大小不变
     *
     * @param spValue
     * @return
     */
    fun sp2px(context: Context, spValue: Float): Int {
        val fontScale = context.resources.displayMetrics.scaledDensity
        return (spValue * fontScale + 0.5f).toInt()
    }

    /**
     * 名片头文字动态设置位置
     * @param context Context? 上下文
     * @param gravity String? 对齐位置
     * @param width Float? 宽度
     * @param height Float? 高度
     * @param x Float? x轴
     * @param y Float? y轴
     * @param fontSize Int? 文字大小
     * @param color String? 文字颜色
     * @param textView TextView? 显示的控件
     */
    fun setBusinessCardTextPosition(
        context: Context?,
        gravity: String?,
        width: Float?,
        height: Float?,
        x: Float?,
        y: Float?,
        fontSize: Int?,
        color: String?,
        textView: TextView?
    ) {
        //        textView?.visibility = View.VISIBLE
        val layoutParams =
            FrameLayout.LayoutParams(getPx(context, width), FrameLayout.LayoutParams.WRAP_CONTENT)
        layoutParams.leftMargin = getPx(context, x)
        layoutParams.topMargin =
            getPx(context, y?.plus((height?.minus(fontSize ?: 0))?.div(2) ?: 0f))
        textView?.layoutParams = layoutParams


        if (color?.length == 4) {
            val sb = StringBuilder()
            sb.append("#")

            (color.indices).map {
                when (it) {
                    1 -> {
                        sb.append(color[it])
                        sb.append(color[it])
                    }
                    2 -> {
                        sb.append(color[it])
                        sb.append(color[it])
                    }
                    3 -> {
                        sb.append(color[it])
                        sb.append(color[it])
                    }
                    else -> {
                    }
                }
            }
            textView?.setTextColor(Color.parseColor(sb.toString()))
        } else {
            color?.let { color -> textView?.setTextColor(Color.parseColor(color)) }
        }


        when (gravity) {
            "left" -> {
                textView?.gravity = Gravity.LEFT
            }
            "right" -> {
                textView?.gravity = Gravity.RIGHT
            }

            "center" -> {
                textView?.gravity = Gravity.CENTER
            }

        }

        textView?.textSize = px2sp(context, fontSize?.toFloat())
    }


    /**
     * 名片头图片动态设置位置
     * @param context Context? 上下文
     * @param path String? 图片路径
     * @param height Float? 高度
     * @param x Float? x轴
     * @param y Float? y轴
     * @param imageView ImageView?显示的控件
     */
    fun setBusinessCardTextIconPosition(
        context: Context?,
        path: String?,
        width: Float?,
        height: Float?,
        x: Float?,
        y: Float?,
        imageView: ImageView?
    ) {
        val layoutParams = FrameLayout.LayoutParams(getPx(context, width), getPx(context, height))
        layoutParams.leftMargin = getPx(context, x)
        layoutParams.topMargin = getPx(context, y)
        imageView?.layoutParams = layoutParams
        imageView?.let { Glide.with(context!!).load(path).into(it) }
    }


    /**
     * 获取屏幕宽度
     * @param context
     * @return
     */
    fun getScreenWidth(context: Context?): Int {
        return context?.resources?.displayMetrics?.widthPixels ?: 0
    }

    /**
     * 获取屏幕高度
     * @param context
     * @return
     */
    fun getScreenHeight(context: Context?): Int {
        return context?.resources?.displayMetrics?.heightPixels ?: 0
    }

    /**
     * 创建一个Shape - GradientDrawable
     *
     * @param strokeWidth - 沿边线厚度；无需传入-1
     * @param roundRadius - 圆角半径；无需传入-1
     * @param shape       - shape绘制类型(rectangle、oval等)；无需传入-1，将采用默认的GradientDrawable.RECTANGLE
     * @param strokeColor - 沿边线颜色；无需传入null/""
     * @param fillColor   - 内部填充颜色
     * @return
     */
    fun createShape(
        strokeWidth: Int,
        roundRadius: Int,
        shape: Int,
        strokeColor: String?,
        fillColor: String?
    ): GradientDrawable? {

        var mStrokeColor = -1

        if (null != strokeColor && strokeColor != "") {
            mStrokeColor = Color.parseColor(strokeColor)
        }
        val fillColor = Color.parseColor(fillColor)
        val gd = GradientDrawable()

        gd.setColor(fillColor)
        if (-1 == shape) {
            gd.shape = GradientDrawable.RECTANGLE
        } else {
            gd.shape = shape
        }
        if (-1 != roundRadius) {
            gd.cornerRadius = roundRadius.toFloat()
        }
        if (-1 != strokeWidth && -1 != mStrokeColor) {
            gd.setStroke(strokeWidth, mStrokeColor)
        }
        return gd
    }

    /**
     * 获取状态栏高度
     *
     * @param context context
     * @return 状态栏高度
     */
    fun getStatusBarHeight(context: Context): Int {
        // 获得状态栏高度
        val resourceId = context.resources.getIdentifier("status_bar_height", "dimen", "android")
        return context.resources.getDimensionPixelSize(resourceId)
    }


    /**
     * 解决InputMethodManager引起的内存泄漏
     * 在Activity的onDestroy方法里调用
     */
    fun fixInputMethodManagerLeak(context: Context) {

        val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        val arr = arrayOf("mCurRootView", "mServedView", "mNextServedView")
        var field: Field? = null
        var objGet: Any? = null
        for (i in arr.indices) {
            val param = arr[i]
            try {
                field = imm.javaClass.getDeclaredField(param)
                if (field.isAccessible === false) {
                    field.isAccessible = true
                }
                objGet = field.get(imm)
                if (objGet != null && objGet is View) {
                    val view = objGet
                    if (view.context === context) {
                        // 被InputMethodManager持有引用的context是想要目标销毁的
                        field.set(imm, null) // 置空，破坏掉path to gc节点
                    } else {
                        // 不是想要目标销毁的，即为又进了另一层界面了，不要处理，避免影响原逻辑,也就不用继续for循环了
                        break
                    }
                }
            } catch (t: Throwable) {
                t.printStackTrace()
            }

        }

    }

    /**
     * 判断是否是AndroidQ
     */
    private fun getSDKVersion(): Boolean {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
    }

    /**
     * 获取选择图片的地址
     * @param media LocalMedia
     * @return String?
     */
    fun getSelectPicture(media: LocalMedia): String? {

        if (media == null) {
            return ""
        }
        //相片路径
        return when {
            getSDKVersion() -> {
                media.androidQToPath
            }
            else -> {
                media.path
            }
        }
    }


    /**
     * @param s 需要复制的内容
     */
    fun copy(context: Context?, s: String?) {

        context?.let {
            val clipboardManager =
                it.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
            val clipData = ClipData.newPlainText("text copy", s)
            clipboardManager.setPrimaryClip(clipData)
            ToastUtils.showToast(it.resources?.getString(R.string.common_copy_succeeded) ?: "")
        }

    }


    /**
     * 往手机通讯录插入联系人
     * @param context Context 上下文
     * @param name String? 名字
     * @param tel String? 电话号码
     * @param email String? 邮箱
     */
    fun insertContact(
        context: Context?,
        name: String? = "",
        tel: String? = "",
        email: String? = ""
    ) {

        PermissionHelper.requestContactsPermission(context, {

            val values = ContentValues()
            // 首先向RawContacts.CONTENT_URI执行一个空值插入，目的是获取系统返回的rawContactId
            val rawContactUri = context?.contentResolver?.insert(RawContacts.CONTENT_URI, values)
            val rawContactId = ContentUris.parseId(rawContactUri)
            // 往data表插入姓名数据
            if (!TextUtils.isEmpty(name)) {
                values.clear()
                values.put(ContactsContract.Contacts.Data.RAW_CONTACT_ID, rawContactId)
                values.put(
                    ContactsContract.Contacts.Data.MIMETYPE,
                    StructuredName.CONTENT_ITEM_TYPE
                ) // 内容类型
                values.put(StructuredName.GIVEN_NAME, name)

                context?.contentResolver?.insert(ContactsContract.Data.CONTENT_URI, values)
            }

            if (!TextUtils.isEmpty(tel) || TextUtils.isEmpty(name)) {
                // 往data表插入电话数据
                values.clear()
                values.put(ContactsContract.Contacts.Data.RAW_CONTACT_ID, rawContactId)
                values.put(ContactsContract.Contacts.Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE) // 内容类型
                values.put(Phone.NUMBER, tel)
                values.put(Phone.TYPE, Phone.TYPE_MOBILE)
                context?.contentResolver?.insert(ContactsContract.Data.CONTENT_URI, values)
            }
            // 往data表插入Email数据
            if (!TextUtils.isEmpty(email)) {
                values.clear()
                values.put(ContactsContract.Contacts.Data.RAW_CONTACT_ID, rawContactId)
                values.put(ContactsContract.Contacts.Data.MIMETYPE, Email.CONTENT_ITEM_TYPE) // 内容类型
                values.put(Email.DATA, email)
                values.put(Email.TYPE, Email.TYPE_WORK)
                context?.contentResolver?.insert(ContactsContract.Data.CONTENT_URI, values)
            }

            ToastUtils.showToast(
                context?.resources?.getString(R.string.common_address_book_saved_successfully) ?: ""
            )
        })

    }

    /**
     * 拨打电话（跳转到拨号界面，用户手动点击拨打）
     * @param context 上下文
     * @param phoneNum 电话号码
     */
    @Deprecated("使用BusinessUtils.callPhone()添加用户行为")
    fun callPhone(context: Context?, phoneNum: String?) {
        if (phoneNum.isNotNullOrEmpty()) {
            if (phoneNum?.contains("*")!!) {
                ToastUtils.showToast("当前号码不对外公开,您无法拨打!")
            } else {
                val intent = Intent(Intent.ACTION_DIAL)
                val data: Uri = Uri.parse("tel:+$phoneNum")
                intent.data = data
                context?.startActivity(intent)
            }
        }
    }

    /**
     * 获取时间类型
     * @param date Date 时间(年月日)
     * @return String? 时间类型
     */
    fun getTimeYMDHMS(date: Date): String {
        val format = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
        return format.format(date)
    }

    /**
     * 获取时间类型
     * @param date Date 时间(年月日)
     * @return String? 时间类型
     */
    fun getTimeYMDHM(date: Date): String {
        val format = SimpleDateFormat("yyyy-MM-dd HH:mm")
        return format.format(date)
    }


    /**
     * 获取时间类型
     * @param date Date 时间(年月日)
     * @return String? 时间类型
     */
    fun getTimeYMD(date: Date): String? {
        val format = SimpleDateFormat("yyyy-MM-dd")
        return format.format(date)
    }

    /**
     * 获取时间类型
     * @param date Date 时间 (年月)
     * @return String? 时间类型
     */
    fun getTimeYM(date: Date): String? {
        val format = SimpleDateFormat("yyyy-MM")
        return format.format(date)
    }

    /**
     * 获取时间类型
     * @param date Date 时间(月日)
     * @return String? 时间类型
     */
    fun getTimeMD(date: Date): String? {
        val format = SimpleDateFormat("MM.dd")
        return format.format(date)
    }

    /**
     * 获取当前年与日
     */
    fun getCurrentYMD(): String? {

        val format = SimpleDateFormat("yyyy-MM-dd")
        val c = Calendar.getInstance()
        return format.format(c.time).toString()

    }

    /**
     * 获取过去多少天时间(结束时候加上当前 需要减去一天)
     */
    fun getPastTimesMonth(amount: Int = 30): String? {

        val format = SimpleDateFormat("yyyy-MM-dd")
        val c = Calendar.getInstance()
        c.time = Date()
        c.add(Calendar.DATE, -(amount - 1))
        val d = c.time
        return format.format(d)

    }


    //读取方法
    fun getJson(context: Context, fileName: String?): String {
        val stringBuilder = StringBuilder()
        try {
            val assetManager = context.assets
            val bf = BufferedReader(InputStreamReader(fileName?.let { assetManager.open(it) }))
            var line: String?
            while (bf.readLine().also { line = it } != null) {
                stringBuilder.append(line)
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return stringBuilder.toString()
    }

    /**
     * 判断是否正常的网址
     * @return true ->是 false->否
     */
    fun isUrl(url: String?): Boolean {
        val regex =
            "^((http||https):\\/\\/)?[\\w\\-_]+(\\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?"
        val pattern = Pattern.compile(regex)
        return pattern.matcher(url).matches()
    }


    /**
     * 将毫秒值转为秒
     * @param time Long 时间
     * @return String? 转换后的秒
     */
    fun getGapTime(time: Long?): String? {

        if (time == 0L) {
            return ""
        }

        return (time?.div(1000)).toString()
    }

    /**
     * 比较两个日期的大小，日期格式为yyyy-MM-dd
     *
     * @param start 开始时间
     * @param end 结束时间
     * @return true 开始时间比较大 false: 结束时间比较大
     */
    fun isDateOneBigger(start: String?, end: String?): Boolean {
        var isBigger = false
        val sdf = SimpleDateFormat("yyyy-MM")
        var dt1: Date? = null
        var dt2: Date? = null
        try {
            dt1 = sdf.parse(start)
            dt2 = sdf.parse(end)
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        if (dt1!!.time > dt2!!.time) {
            isBigger = true
        } else if (dt1.time < dt2.time) {
            isBigger = false
        }
        return isBigger
    }

    /**
     *
     * @param context 上下文对象
     * @param dir 存储目录
     * @return SD卡路径
     */
    fun getFilePath(context: Context, dir: String): String? {
        //判断SD卡是否可用
        val directoryPath = if (MEDIA_MOUNTED == Environment.getExternalStorageState()) {
            context.getExternalFilesDir(dir)?.absolutePath
        } else {
            //没内存卡就存机身内存
            "${context.filesDir}${File.separator}$dir"
        }
        val file = File(directoryPath)
        if (!file.exists()) { //判断文件目录是否存在
            file.mkdirs()
        }
        return directoryPath
    }


    /**
     * 通过uri获取bitmap
     */
    private fun getBitmapFromUri(context: Context, uri: Uri?): Bitmap? {
        return try {
            // 读取uri所在的图片
            MediaStore.Images.Media.getBitmap(context.contentResolver, uri)
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }


    /**
     * @param @param  bitmap
     * @param @return 设定文件
     * @return String    返回类型
     * @Title: bitmapToBase64
     */
    private fun bitmapToBase64(bitmap: Bitmap?): String {

        // 要返回的字符串
        var result = ""
        var outputStream: ByteArrayOutputStream? = null
        try {
            if (bitmap != null) {
                outputStream = ByteArrayOutputStream()
                //压缩只对保存有效果bitmap还是原来的大小
                bitmap.compress(Bitmap.CompressFormat.JPEG, 30, outputStream)
                outputStream.flush()
                outputStream.close()
                // 转换为字节数组
                val byteArray = outputStream.toByteArray()

                // 转换为字符串
                result = Base64.encodeToString(byteArray, Base64.DEFAULT)
            } else {
                return ""
            }
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            try {
                outputStream?.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
        return result
    }


    /**
     * 保存到系统相册
     */

    fun saveImage(context: Context, bitmap: Bitmap) {

        PermissionHelper.requestReadExternalStoragePermission(context, {
            val displayName = "${System.currentTimeMillis()}.jpg"
            val mimeType = "image/jpeg"
            val compressFormat = Bitmap.CompressFormat.JPEG

            val values = ContentValues()
            values.put(MediaStore.MediaColumns.DISPLAY_NAME, displayName)
            values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM)
            } else {
                values.put(
                    MediaStore.MediaColumns.DATA,
                    "${Environment.getExternalStorageDirectory().path}/${Environment.DIRECTORY_DCIM}/$displayName"
                )
            }
            val uri =
                context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
            if (uri != null) {
                val outputStream = context.contentResolver.openOutputStream(uri)
                if (outputStream != null) {
                    bitmap.compress(compressFormat, 100, outputStream)
                    outputStream.close()
                    ToastUtils.showToast("保存成功,快去分享吧~")
                }
            } else {
                ToastUtils.showToast("保存失败")
            }
        })

    }


    /**
     * View 转Bitmap
     */
    fun loadBitmapFromView(v: View): Bitmap? {
        val w = v.width
        val h = v.height
        val bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
        val c = Canvas(bmp)
        c.drawColor(Color.WHITE)
        //如果不设置canvas画布为白色，则生成透明
        v.layout(0, 0, w, h)
        v.draw(c)
        return bmp
    }

    /**
     * 数值的装换
     * @param count Int 需要装换的数值
     * @return String? 装换后的数值
     */
    fun getNumericalConversion(count: Int?): String? {
        if (count != null) {
            return if (count > 999) {
                "999+"
            } else {
                count.toString()
            }
        }
        return "0"
    }

    /**
     * 数值的装换 超过9999人显示为1万
     * @param count Int 需要装换的数值
     * @return String? 装换后的数值
     */
    fun getBrowseCount(count: Int?): String? {
        if (count != null) {
            return if (count > 9999) {
                "1万+"
            } else {
                count.toString()
            }
        }
        return "0"
    }


    /**
     * 判断文件名后缀
     * @param suffix String? 后缀
     * @return Boolean true:文件 false:视频
     */
    fun browseDocument(suffix: String?): Boolean {

        return suffix == "doc" || suffix == "docx" || suffix == "ppt" || suffix == "pptx" || suffix == "xls" || suffix == "xlsx" || suffix == "txt" || suffix == "pdf" || suffix == "epub"
    }

    /**
     * 获取当前进程名
     */
    fun getProcessName(pid: Int): String {
        var reader: BufferedReader? = null
        try {
            reader = BufferedReader(FileReader("/proc/$pid/cmdline"))
            var processName = reader!!.readLine()
            if (!TextUtils.isEmpty(processName)) {
                processName = processName.trim()
            }
            return processName
        } catch (throwable: Throwable) {
            throwable.printStackTrace()
        } finally {
            try {
                if (reader != null) {
                    reader?.close()
                }
            } catch (exception: IOException) {
                exception.printStackTrace()
            }
        }
        return ""
    }

    /**
     * @param activity 目标Activity
     * @description: Activity跳转
     */
    fun goActivity(context: Context, activity: Class<*>?) {
        goActivity(context, activity, null)
    }

    /**
     * @param activity 目标Activity
     * @param bundle   携带的数据
     * @description: Activity跳转
     */
    fun goActivity(context: Context, activity: Class<*>?, bundle: Bundle?) {
        goActivity(context, activity, bundle, false)
    }

    /**
     * @param activity 目标Activity
     * @param bundle   携带的数据
     * @description: Activity跳转
     */
    fun goActivity(context: Context, activity: Class<*>?, bundle: Bundle?, isFinish: Boolean) {
        val intent = Intent(context, activity!!)
        if (bundle != null) {
            intent.putExtras(bundle)
        }
        context.startActivity(intent)
        if (isFinish) {
            (context as Activity).finish()
        }
    }


    /**
     * @param activity    目标Activity
     * @param bundle      携带的数据
     * @param requestCode 请求码
     * @param isFinish    是否关闭页面
     * @description: Activity跳转, 带返回结果
     */
    fun goActivityForResult(
        context: Context,
        activity: Class<*>?,
        bundle: Bundle?,
        requestCode: Int,
        isFinish: Boolean
    ) {
        val intent = Intent(context, activity!!)
        if (bundle != null) {
            intent.putExtras(bundle)
        }
        (context as Activity).startActivityForResult(intent, requestCode)
        if (isFinish) {
            context.finish()
        }
    }


    /**
     * @param bundle     携带的数据
     * @param resultCode 返回标示码
     * @description: ForResult跳转, 带返回结果
     */
    fun goResult(context: Context, bundle: Bundle?, resultCode: Int) {
        val intent = (context as Activity).intent
        if (bundle != null) {
            intent.putExtras(bundle)
        }
        context.setResult(resultCode, intent)
        context.finish()
    }


    /**
     * @param activity 目标Activity
     * @param bundle   携带的数据
     * @description: Activity跳转
     */
    fun goMainActivity(context: Context, activity: Class<*>?, bundle: Bundle?, isFinish: Boolean) {
        val intent = Intent(context, activity!!)
        intent.flags =
            Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK //关闭除了MainActivity所有的栈顶的Activity
        if (bundle != null) {
            intent.putExtras(bundle)
        }
        context.startActivity(intent)
        if (isFinish) {
            (context as Activity).finish()
        }
    }


    //判断是否空 true:不为空 false:为空
    fun CharSequence?.isNotNullOrEmpty(): Boolean {
        return this != "null" && this != null && this.isNotEmpty()
    }

    //判断是否空 true:为空 false:为不空
    fun CharSequence?.isNullOrEmpty(): Boolean {

        return this == null || this.isEmpty() || this == "null"
    }

    /**
     * 判断是否不为空
     * @param text String? 需要判断的文字
     * @return Boolean true:不为空 false:为空
     */
    fun isNotNullOrEmpty(text: String?): Boolean {
        return text != "null" && text != null && text.isNotEmpty()
    }

    /**
     * 判断是否为空
     * @param text String? 需要判断的文字
     * @return Boolean     // true:为空 false:为不空
     */
    fun isNullOrEmpty(text: String?): Boolean {
        return text == null || text.isEmpty() || text == "null"
    }


    /**
     * 获取textView的高度
     * @param textView TextView?
     * @return Int 返回textView的高度
     */
    fun getTextWidth(textView: TextView?): Int {

        val text = textView?.text.toString()
        val rect = Rect()
        val paint = textView?.paint
        paint?.getTextBounds(text, 0, text.length, rect)
        return rect.width()
    }


    /**
     * 价格的转换 保留几位小数，且四舍五入
     * @param price String? 价格
     * @param scale Int? 保留几位小数 (默认保留2位小数)
     * @return String? 返回价格
     */
    fun getBigDecimal(price: String?, scale: Int? = 2): String? {

        return if (isNotNullOrEmpty(price)) {
            BigDecimal(price).setScale(scale ?: 2, RoundingMode.HALF_UP).toString()
        } else {

            ""
        }
    }


    /**
     * 获取图片地址
     */
    fun LocalMedia.extPicturePath(): String {
        var path = path
        if (PictureMimeType.isContent(path)) {
            path = realPath
        }
        if (path.isNullOrEmpty()) {
            path = androidQToPath
        }
        return path
    }

    /**
     * @param red   区间 [0,255]
     * @param green 区间 [0,255]
     * @param blue  区间 [0,255]
     * @param alpha 区间 [0,1]
     */
    fun getRBGA(red: Float, green: Float, blue: Float, alpha: Float = 0f): Int {
        var r = Integer.toHexString(red.toInt())
        var g = Integer.toHexString(green.toInt())
        var b = Integer.toHexString(blue.toInt())
        var a = Integer.toHexString((alpha * 255).toInt())

        if (a.length == 1) a = "0$a"
        if (r.length == 1) r = "0$r"
        if (g.length == 1) g = "0$g"
        if (b.length == 1) b = "0$b"

        return Color.parseColor("#${a}${r}${g}${b}")
    }


    /**
     * @param red   区间 [0,255]
     * @param green 区间 [0,255]
     * @param blue  区间 [0,255]
     * @param alpha 区间 [0,255]
     */
    fun getRBG(red: Int = 255, green: Int = 255, blue: Int = 255, alpha: Int = 255): Int {
        return Color.argb(alpha, red, green, blue)
    }


    /**
     * 计算颜色
     *
     * @param color color值 颜色值
     * @param alpha alpha值 透明度
     */
    private fun getColor(@ColorInt color: Int, alpha: Int): Int {
        if (alpha == 0) {
            return color
        }
        val a = 1 - alpha / 255f
        var red = color shr 16 and 0xff
        var green = color shr 8 and 0xff
        var blue = color and 0xff
        red = (red * a + 0.5).toInt()
        green = (green * a + 0.5).toInt()
        blue = (blue * a + 0.5).toInt()
        return 0xff shl 24 or (red shl 16) or (green shl 8) or blue
    }


    /**
     * 文件大小单位转换
     */
    fun Long.extByteToMB(): String {
        val size = this
        val kb: Long = 1024
        val mb = kb * 1024
        val gb = mb * 1024
        return when {
            size >= gb -> String.format("%.1f GB", size.toFloat() / gb)
            size >= mb -> {
                val f = size.toFloat() / mb
                String.format(if (f > 100) "%.0f MB" else "%.1f MB", f)
            }
            size > kb -> {
                val f = size.toFloat() / kb
                String.format(if (f > 100) "%.0f KB" else "%.1f KB", f)
            }
            else -> String.format("%d B", size)

        }
    }
}






